package concurrecy;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class Blocker {
    public synchronized void block() {
        while(!Thread.interrupted()) {
            try {
                System.out.println(Thread.currentThread().getName() + " wait");
                wait();
                System.out.print(Thread.currentThread().getName() + " continue ");
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + " interrupted");
                break;
            }
        }
        System.out.println(Thread.currentThread().getName() + " exit from while");
    }

    public synchronized void n() {
        System.out.print("notify ");
        notify();
    }

    public synchronized void na() {
        System.out.print("notifyAll ");
        notifyAll();
    }
}

class BlockerTask implements Runnable {

    public static Blocker blocker = new Blocker();

    @Override
    public void run() {
        blocker.block();
    }
}

class BlockerTask2 implements Runnable {

    public static Blocker blocker = new Blocker();

    @Override
    public void run() {
        blocker.block();
    }
}

/**
 * notify 只唤醒一个当前对象上等待中的线程
 * notifyAll 唤醒当前对象上所有等待的线程
 */
public class NotifyDemo {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            service.execute(new BlockerTask());
        }
        service.execute(new BlockerTask2());

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            boolean f = true;
            @Override
            public void run() {
                if(f)
                    BlockerTask.blocker.n();
                else
                    BlockerTask.blocker.na();
                System.out.println();
                f = !f;
            }
        }, 500, 500);

        TimeUnit.SECONDS.sleep(3);
        System.out.println("timer.cancel");
        timer.cancel();

        TimeUnit.SECONDS.sleep(3);
        System.out.println("blockTask2 notify");
        BlockerTask2.blocker.n();
        TimeUnit.SECONDS.sleep(3);
        System.out.println("blockTask2 notifyAll");
        BlockerTask2.blocker.na();

        System.out.println("shutdown now");
        service.shutdownNow();
    }
}
